package com.tobeface.sns.domain.security;

import java.util.List;
import java.util.Set;

import javax.annotation.Nullable;

import org.apache.commons.lang.StringUtils;
import org.springframework.data.mongodb.core.mapping.Document;

import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.kissme.core.domain.AbstractDomain;
import com.tobeface.sns.infrastructure.shiro.MD5HashUtils;

/**
 * 
 * @author loudyn
 * 
 */
@Document(collection = "member")
public class Member extends AbstractDomain {
	
	private static final long serialVersionUID = 1L;
	private String username;
	private String password;

	private int level;

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public int getLevel() {
		return level;
	}

	public void setLevel(int level) {
		this.level = level;
	}

	public boolean isActive() {
		return false;
	}

	/**
	 * 
	 * @param password
	 * @return
	 */
	public boolean isCorrectPassword(String password) {
		return StringUtils.equals(getPassword(), MD5HashUtils.asMD5(password, getUsername()));
	}
	
	/**
	 * 
	 * @return
	 */
	public List<Role> getRoles() {
		switch (getLevel()) {
		case 0:
			return ImmutableList.of(Role.ADMIN);
		default:
			return ImmutableList.of(Role.COMMON_MEMBER);
		}
	}
	
	/**
	 * 
	 * @return
	 */
	public List<String> getRoleNames() {
		return Lists.transform(getRoles(), new Function<Role, String>() {

			@Nullable
			public String apply(@Nullable Role input) {
				return input.getName();
			}
		});
	}

	/**
	 * 
	 * @return
	 */
	public List<Permission> getPermissions() {
		List<Permission> permissions = Lists.newLinkedList();
		for (Role role : getRoles()) {
			permissions.addAll(role.getPermissions());
		}

		return permissions;
	}

	/**
	 * 
	 * @return
	 */
	public List<String> getPermissionNames() {
		return Lists.transform(getPermissions(), new Function<Permission, String>() {

			@Nullable
			public String apply(@Nullable Permission input) {
				return input.getName();
			}

		});
	}

	public enum Role {

		COMMON_MEMBER("common-member") {

			private List<Permission> permissions = ImmutableList.of(Permission.CREATE_LIFE_THINKING);

			@Override
			public List<Permission> getPermissions() {
				return permissions;
			}

		},

		ADMIN("admin") {
			private List<Permission> permissions = ImmutableList.of(Permission.CREATE_LIFE_THINKING);

			@Override
			public List<Permission> getPermissions() {
				return permissions;
			}
		};

		private final String name;

		private Role(String name) {
			this.name = name;
		}

		public final String getName() {
			return name;
		}

		public abstract List<Permission> getPermissions();
	}

	public enum Permission {

		CREATE_USER_JOB("user-job:create"), EDIT_USER_JOB("user-job:edit"),
		CREATE_USER_EDUCATION("user-education:create"), EDIT_USER_EDUCATION("user-education:edit"),
		EDIT_USER_PROFILES("user-profiles:edit"),
		CREATE_LIFE_THINKING("life-thinking:create");

		private final String name;

		private Permission(String name) {
			this.name = name;
		}  

		public String getName() {
			return name;
		}
	}
 
	public Member encodePassword() {
		this.password = MD5HashUtils.asMD5(getPassword(), getUsername());
		return this;
	}

	public Set<String> getRoleAsStrings() { 
		Set<String> roleAsStrings = Sets.newHashSet();
		for (Role role : getRoles()) {
			roleAsStrings.add(role.getName());
		}

		return roleAsStrings;
	}

	public Set<String> getPermissionAsStrings() {
		Set<String> permissionAsStrings = Sets.newHashSet();
		for (Permission permission : getPermissions()) {
			permissionAsStrings.add(permission.getName());
		}

		return permissionAsStrings;
	}
}
